package com.sundhage.util {
	import flash.utils.*;
	import flash.xml.*;
	
	
	public class JSXMLHelper {
	// TODO: Synka med XML2OBJ (blir säkert en gör om, gör rätt.... lägg på UMO-timmarna)
	
		static public function OBJ2XML(o:Object, escapeData:Boolean = true):String {
			var sRet:String = "<items>";
			parse(o, "", true);
			sRet += "</items>";
			return sRet;
			
			
			function parse(data:*, id:String, firstRun:Boolean=false):void {
				if (getQualifiedClassName(data) == "Array") {
					sRet += "<item type='Array' id='"+id+"'>";
					for (var i:int = 0; i<data.length; i++) parse(data[i], String(i));
					sRet += "</item>";
				} else if (getQualifiedClassName(data) == "Object") {
					if (!firstRun) sRet += "<item type='Object' id='"+id+"'>";
					for (var prop:* in data) {
						parse(data[prop], prop);
					}
					if (!firstRun) sRet += "</item>";
				} else if (getQualifiedClassName(data) == "String") {
					sRet += "<item type='String' id='"+id+"'>"+fix(data)+"</item>";
				} else if (data == parseInt(data)) {
					sRet += "<item type='Number' id='"+id+"'>"+fix(data)+"</item>";
				}
			
			}
			
			function fix(data:*):String {
				if (data == "") return data;
				if (escapeData) return escape(data); else return data;
			}
		}
/*
	STRUKTUR
			var s:String = "<items>";
			s += "<item type='Object' id='myObject'>";
				s += "<item type='Number' id='nummer'>444</item>";
				s += "<item type='String' id='str'>Tjohooo</item>";
			s += "</item>";
			s += "<item type='Array' id='myArray'>";
				s += "<item type='Number' id='unused'>3</item>";
				s += "<item type='Number' id='unused'>1</item>";
				s += "<item type='Object' id='unused'>'";
					s += "<item type='String' id='nested'>ohojoj</item>";
					s += "<item type='Number' id='strange'>5</item>";
				s += "</item>"; 
			s += "</item>"
			s += "<item type='Number' id='myNumber'>34.3</item>";
			s += "<item type='String' id='myString'>Hallihall%192</item></items>";	

		man kan alltså göra Object i Object, Array i Object osv osv...
		id är variabelnamn, type kan vara Number, String, Object eller Array
*/

		static public function XML2OBJ(xml:XMLDocument, dataIsEscaped:Boolean = true):Object {
			var node:XMLNode = xml.firstChild;
			var root:Array = node.childNodes;
			return parseList(root, dataIsEscaped);
			
			
			// help funcs
			function parseList(list:Array, dataIsEscaped:Boolean, o:* = null, isArray:Boolean=false):* {
				if (!o) o = new Object();

				for (var i:int = 0; i < list.length; i++) {
					if(list[i].attributes.type == "Number") {
						if (isArray) {
							setArray(dataIsEscaped, o, list[i].firstChild, "Number");
							
						} else 
							setData(dataIsEscaped, o, String(list[i].attributes.id), list[i].firstChild, "Number");
					}
					if(list[i].attributes.type == "String") {
						if (isArray) {
							setArray(dataIsEscaped, o, list[i].firstChild, "String");
						}
						else
							setData(dataIsEscaped, o, String(list[i].attributes.id), list[i].firstChild, "String");							
					}
					if(list[i].attributes.type == "Array") {
						if (isArray) {
							o.push(parseList(list[i].childNodes, dataIsEscaped, null, true));
							
						} else {
							o[list[i].attributes.id] = new Array();
							parseList(list[i].childNodes, dataIsEscaped, o[list[i].attributes.id], true);
						}
					}
					
					if(list[i].attributes.type == "Object") {
						if (isArray) {
							o.push(parseList(list[i].childNodes, dataIsEscaped, null));
						} else {
							o[list[i].attributes.id] = new Object();
							parseList(list[i].childNodes, dataIsEscaped, o[list[i].attributes.id]);
						}
					}
				}
				return o;
			}
			
			function setData(dataIsEscaped:Boolean, o:Object, prop:String, val:*, type:String):void {
				if (dataIsEscaped) {
					if (type == "String") o[prop] = unescape(val);
					if (type == "Number") o[prop] = Number(unescape(val));
				} else {
					if (type == "String") o[prop] = String(val);
					if (type == "Number") o[prop] = Number(val);					
				}
				if (o[prop] == "null") o[prop] = "";
			}
			function setArray(dataIsEscaped:Boolean, a:Array, val:*, type:String):void {
				if (dataIsEscaped) {
					if (type == "String") a.push(unescape(val));
					if (type == "Number") a.push(Number(unescape(val)));
				} else {
					if (type == "String") a.push(String(val));
					if (type == "Number") a.push(Number(val));
				}
				if (a[a.length-1] == "null") a[a.length-1] = "";
			}

		}
		
		
		public function JSXMLHelper() {
		}
	}
}